/**
 * This file is part of aion-emu <aion-emu.com>.
 *
 *  aion-emu is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  aion-emu is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with aion-emu.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.aionemu.gameserver.model.account;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.aionemu.gameserver.model.gameobjects.player.Storage;

/**
 * This class represents game account and is holding such informations as:
 * <ul>
 * <li>account id</li>
 * <li>account name</li>
 * <li> {@link AccountTime account time info}</li>
 * <li>a list of {@link PlayerAccountData} objects each of which keeping information about player that must be available
 * on character selection screen.</li>
 * </ul>
 * 
 * @author SoulKeeper
 */
public class Account implements Iterable<PlayerAccountData>
{
	/** Unique id of this account (it's generated by login server) */
	private final int						id;
	/** Unique name of this account */
	private String							name;
	/**
	 * Access level
	 */
	private byte							accessLevel;
	/**
	 * Membership of this account
	 */
	private byte							membership;
	
	private AccountTime						accountTime;

	private Map<Integer, PlayerAccountData>	players	= new HashMap<Integer, PlayerAccountData>();
	
	private Storage							accountWarehouse;

	public Account(int id)
	{
		this.id = id;
	}

	public int getId()
	{
		return id;
	}

	public String getName()
	{
		return name;
	}

	public void setName(String name)
	{
		this.name = name;
	}

	public AccountTime getAccountTime()
	{
		return accountTime;
	}

	public void setAccountTime(AccountTime accountTime)
	{
		this.accountTime = accountTime;
	}

	/**
	 * @return the accessLevel
	 */
	public byte getAccessLevel()
	{
		return accessLevel;
	}

	/**
	 * @param accessLevel the accessLevel to set
	 */
	public void setAccessLevel(byte accessLevel)
	{
		this.accessLevel = accessLevel;
	}

	/**
	 * @return the membership
	 */
	public byte getMembership()
	{
		return membership;
	}

	/**
	 * @param membership the membership to set
	 */
	public void setMembership(byte membership)
	{
		this.membership = membership;
	}

	@Override
	public boolean equals(Object o)
	{
		if(this == o)
		{
			return true;
		}

		if(!(o instanceof Account))
		{
			return false;
		}

		Account account = (Account) o;

		return id == account.id;
	}

	@Override
	public int hashCode()
	{
		return id;
	}

	/**
	 * @param chaOid
	 * @return PlayerAccountData
	 */
	public PlayerAccountData getPlayerAccountData(int chaOid)
	{
		return players.get(chaOid);
	}

	/**
	 * @param accPlData
	 */
	public void addPlayerAccountData(PlayerAccountData accPlData)
	{
		players.put(accPlData.getPlayerCommonData().getPlayerObjId(), accPlData);
	}

	/**
	 * @return the accountWarehouse
	 */
	public Storage getAccountWarehouse()
	{
		return accountWarehouse;
	}

	/**
	 * @param accountWarehouse the accountWarehouse to set
	 */
	public void setAccountWarehouse(Storage accountWarehouse)
	{
		this.accountWarehouse = accountWarehouse;
	}

	/** Returns the number of players that are on this account */
	public int size()
	{
		return players.size();
	}

	/**
	 * Sorts the accounts on last online.
	 */
	public ArrayList<PlayerAccountData> getSortedAccountsList()
	{
		ArrayList<PlayerAccountData> list = new ArrayList<PlayerAccountData>();
		list.addAll(players.values());
		Collections.sort(list, new Comparator<PlayerAccountData>(){
			@Override
			public int compare(PlayerAccountData x, PlayerAccountData y)
			{
				Timestamp t1 = x.getPlayerCommonData().getLastOnline();
				Timestamp t2 = y.getPlayerCommonData().getLastOnline();
				if(t2 == null)
					return 1;
				else if(t1 == null)
					return -1;
				return y.getPlayerCommonData().getLastOnline().compareTo(x.getPlayerCommonData().getLastOnline());
			}
		});
		return list;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Iterator<PlayerAccountData> iterator()
	{
		return players.values().iterator();
	}
}
